/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */
package com.ecarx.systemui.plugin.controller

import android.content.Context
import android.net.wifi.ScanResult
import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiInfo
import android.util.Log
import com.ecarx.systemui.plugin.utils.LogUtils
import ecarx.openapi.net.wifi.ActionListener
import ecarx.openapi.net.wifi.ExternalWifiStaManager
import ecarx.openapi.net.wifi.IExternalWifiSta
import ecarx.openapi.net.wifi.StaConnectionListener
import ecarx.openapi.net.wifi.StaScanResultListener
import ecarx.openapi.net.wifi.StaStateListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Collections

/**
 * TCAM wifi
 */
object TcamWifiController {

    private const val TAG = "TcamWifiController"

    var mWifiSta: IExternalWifiSta? = null
    var mWifiStateListeners:MutableList<(state: Int) -> Unit?> = mutableListOf()
    var mWifiConnectListeners:MutableList<ConnectionStatusListener> = mutableListOf()

    fun init(context: Context) {
        ExternalWifiStaManager.get(context).init { ready: Boolean ->
            if (ready) {
                mWifiSta = ExternalWifiStaManager.get(context)
                mWifiSta?.registerConnectionListener(object : StaConnectionListener {
                    override fun onStateChanged(state: Int, wifiInfo: WifiInfo) {
                        mWifiConnectListeners.forEach {
                            it.onStateChanged(state, wifiInfo)
                        }
                    }

                    override fun onError(code: Int) {
                        mWifiConnectListeners.forEach {
                            it.onError(code)
                        }
                    }
                })

                mWifiSta?.registerWifiStateListener(object : StaStateListener {
                    override fun onStateChanged(state: Int) {
                        mWifiStateListeners.forEach { listener ->
                            listener.invoke(state)
                        }
                    }
                })
            }
        }
    }

    fun getWifiState(): Int{
        return mWifiSta?.wifiState ?: -1
    }

    fun isWifiEnabled(): Boolean{
        return mWifiSta?.isWifiEnabled ?: false
    }
    fun setWifiEnabled(enable: Boolean){
        mWifiSta?.isWifiEnabled = enable
    }
    fun registerWifiStateListener(listener: (state: Int) -> Unit?){
        mWifiStateListeners.add(listener)
    }

    fun registerWifiConnectListener(listener: ConnectionStatusListener){
        mWifiConnectListeners.add(listener)
    }

    fun getScanWifiList(onScanWifiList: (dataList: List<WifiData>) -> Unit){
        mWifiSta?.startScan()
        mWifiSta?.registerScanResultListener(object : StaScanResultListener {
            override fun onScanResulted(result: Boolean) {
                LogUtils.d(TAG, "onScanResulted() called with: result = $result")
                // 扫描到 wifi 列表
                val scanResults = mWifiSta?.scanResults ?: Collections.emptyList()
                // 扫描结果
                onScanWifiList.invoke(getScanDevice(scanResults))
            }
        })
    }

    private fun getScanDevice(scanResults: List<ScanResult>): List<WifiData> {
        val configurationList = mWifiSta?.configuredNetworks //已经保存密码的WiFi
        val connectionWifi = getConnectionWifi()
        val wifiList = mutableListOf<WifiData>()
        for (scanResult in scanResults) {
            if (scanResult.SSID.isNullOrEmpty()) {
                continue
            }
            if (scanResult.SSID == connectionWifi?.ssid) {
                continue
            }
            val isRepeat = wifiList.any { it.ssid == scanResult.SSID }
            if (!isRepeat) {
                val configuration = configurationList?.find { removeQuotationMarks(it.SSID) == scanResult.SSID }
                val netId = configuration?.networkId ?: 0
                val wifiData = WifiData(
                    netId,
                    scanResult.SSID,
                    formatLevel(scanResult.level),
                    scanResult.BSSID,
                    "",
                    securityType(scanResult.capabilities), configuration != null
                )
                wifiList.add(wifiData)
            }
        }
        //根据是否已经保存密码与信号强度降序排序
        wifiList.sortWith(kotlin.Comparator { u1, u2 ->
            if (u1.isSavePwd) {
                u2.isSavePwd.compareTo(u1.isSavePwd)
            } else {
                u2.rssi.compareTo(u1.rssi)
            }
        })
        Log.d(TAG, "getScanDevice: ${wifiList}")
        return wifiList
    }

    /**
     * 获取当前连接的WiFi网络
     */
    fun getConnectionWifi(): WifiData? {
        val wifiInfo = mWifiSta?.connectionInfo ?: return null
        if (wifiInfo.ssid.contains("unknown ssid")){
            //在频繁的切换WiFi与重连WiFi底层会返回 unknown ssid, 这里将其排除掉
            return null
        }

        return WifiData(
            wifiInfo.networkId,
            removeQuotationMarks(wifiInfo.ssid),
            formatLevel(wifiInfo.rssi),
            wifiInfo.bssid,
            getStringId(wifiInfo.ipAddress),
            WiFiPwdType.ESS,
            true
        )
    }

    private fun removeQuotationMarks(content: String): String {
        return content.substring(1, content.length - 1)
    }

    private fun addQuotationMarks(content: String): String {
        return "\"" + content + "\""
    }

    private fun formatLevel(rssi: Int): Int {
        return if (rssi < -97) {
            0
        } else if (rssi < -87) {
            1
        } else if (rssi < -75) {
            2
        } else if (rssi < -63) {
            3
        } else {
            4
        }
    }

    private fun getStringId(idString: Int): String {
        val sb = StringBuffer()
        var b = idString shr 0 and 0xff
        sb.append("$b.")
        b = idString shr 8 and 0xff
        sb.append("$b.")
        b = idString shr 16 and 0xff
        sb.append("$b.")
        b = idString shr 24 and 0xff
        sb.append(b)
        return sb.toString()
    }

    private fun securityType(capabilities: String?): WiFiPwdType {
        if (capabilities == null || capabilities.isEmpty()) {
            return WiFiPwdType.ESS
        }
        // 如果包含WAP-PSK的话，则为WAP加密方式
        if (capabilities.contains("WPA-PSK") || capabilities.contains("WPA2-PSK")) {
            return WiFiPwdType.WAP
        } else if (capabilities.contains("WPA2-EAP")) {
            return WiFiPwdType.WPA2_EAP
        } else if (capabilities.contains("WEP")) {
            return WiFiPwdType.WEP
        } else if (capabilities.contains("ESS")) {
            // 如果是ESS则没有密码
            return WiFiPwdType.ESS
        }
        return WiFiPwdType.ESS
    }


    fun connect(wifiData: WifiData) {
        connect(wifiData, "")
    }

    fun connect(wifiData: WifiData, password: String) {
        val configurationList = mWifiSta?.configuredNetworks //已经保存密码的WiFi
        val isSave = configurationList?.any {
            removeQuotationMarks(it.SSID) == wifiData.ssid
        } ?: false
        if (isSave) {
            //如果是已经保存密码的的WiFi就重新连接
            mWifiSta?.enableNetwork(wifiData.netId, true)
        } else {
            val wifiConfiguration = WifiConfiguration()
            //清除一些默认wifi的配置
            wifiConfiguration.allowedAuthAlgorithms.clear()
            wifiConfiguration.allowedGroupCiphers.clear()
            wifiConfiguration.allowedKeyManagement.clear()
            wifiConfiguration.allowedPairwiseCiphers.clear()
            wifiConfiguration.allowedProtocols.clear()
            wifiConfiguration.SSID = addQuotationMarks(wifiData.ssid)
            when (wifiData.capabilities) {
                WiFiPwdType.ESS -> {
                    wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
                }
                WiFiPwdType.WAP -> {
                    wifiConfiguration.preSharedKey = addQuotationMarks(password)
                    wifiConfiguration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)
                    wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP)
                    wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
                    wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP)
                    wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)
                    wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP)
                    wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN)
                    wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA)
                    wifiConfiguration.status = WifiConfiguration.Status.ENABLED
                }
                WiFiPwdType.WEP -> {
                    wifiConfiguration.wepKeys[0] = addQuotationMarks(password)
                    wifiConfiguration.wepTxKeyIndex = 0;
                    wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                    wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                }
                WiFiPwdType.WPA2_EAP -> {
                    //不支持企业WiFi密码
                }
            }

            // 连接网络
//            val netId = mWifiSta?.addNetwork(wifiConfiguration) ?: -1
//            mWifiSta?.enableNetwork(netId, true)
            // 自动合并以上两步
            mWifiSta?.connect(wifiConfiguration, null)
        }
    }

    fun disconnect() {
        CoroutineScope(Dispatchers.IO).launch {
            val wifiData = getConnectionWifi() ?: return@launch
            mWifiSta?.disconnect()
        }
    }

    interface ConnectionStatusListener {
        fun onStateChanged(state: Int, wifiInfo: WifiInfo)

        fun onError(code: Int)
    }
}